package com.dal.elasticsearch.service.impl;

import cn.hutool.json.JSONUtil;
import com.dal.elasticsearch.enums.FieldType;
import com.dal.elasticsearch.pojo.EsGoodsVo;
import com.dal.elasticsearch.pojo.Event;
import com.dal.elasticsearch.pojo.Log;
import com.dal.elasticsearch.service.IndexService;

import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.RestStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * @ClassName IndexServiceImpl
 * @Author jian
 * @Date 10:42 AM 2022/10/14
 **/
@Service
public class IndexServiceImpl implements IndexService {

    @Autowired
    private RestHighLevelClient client;

    @Override
    public void createIndex(String indexName) {
        try {
            CreateIndexRequest index = new CreateIndexRequest(indexName);
            XContentBuilder xContentBuilder = generateBuilder(EsGoodsVo.class);
            index.source(xContentBuilder);
            client.indices().create(index, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> void createIndex(String indexName, T entity) {
        try {
            Class<?> aClass = entity.getClass();
            CreateIndexRequest index = new CreateIndexRequest(indexName);
            XContentBuilder xContentBuilder = generateBuilder(aClass);
            index.source(xContentBuilder);
            client.indices().create(index, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public void deleteIndex(String indexName){
        AcknowledgedResponse deleteResponse = null;
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        try {
            deleteResponse = client.indices().delete(request, RequestOptions.DEFAULT);
            System.out.println("删除成功" + JSONUtil.toJsonPrettyStr(deleteResponse));
        } catch (ElasticsearchException e) {
            if (e.status() == RestStatus.CONFLICT) {
                System.out.println("删除失败，版本号冲突" + deleteResponse.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public void indexJsonDocs(String indexName, Map<Integer,String> docs) {
        try {
            if (null == docs || docs.size() <= 0) {
                return;
            }
            BulkRequest request = new BulkRequest();
            for (Integer key : docs.keySet()) {
                request.add(
                        new IndexRequest(indexName).id(String.valueOf(key)).source(docs.get(key), XContentType.JSON)
                );
            }
            //for (T doc : docs) {
//                request.add(
//                        new IndexRequest(indexName).id(String.valueOf(doc.getId())).source(JSON.toJSONString(doc), XContentType.JSON)
//                );
            //}
            BulkResponse bulkResponse = client.bulk(request, RequestOptions.DEFAULT);
            if (bulkResponse != null) {
                for (BulkItemResponse bulkItemResponse : bulkResponse) {
                    DocWriteResponse itemResponse = bulkItemResponse.getResponse();

                    if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX
                            || bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) {
                        IndexResponse indexResponse = (IndexResponse) itemResponse;
                        System.out.println("新增成功" + indexResponse.toString());
                    } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) {
                        UpdateResponse updateResponse = (UpdateResponse) itemResponse;
                        System.out.println("修改成功" + updateResponse.toString());
                    } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) {
                        DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
                        System.out.println("删除成功" + deleteResponse.toString());
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public XContentBuilder generateBuilder(Class clazz) throws IOException {
        // 获取索引名称及类型
        // Document doc = (Document) clazz.getAnnotation(Document.class);
        // System.out.println(doc.index());
        // System.out.println(doc.type());

        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        builder.startObject("properties");
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field f : declaredFields) {
            if (f.isAnnotationPresent(com.dal.elasticsearch.annotation.Field.class)) {
                // 获取注解
                com.dal.elasticsearch.annotation.Field declaredAnnotation = f.getDeclaredAnnotation(com.dal.elasticsearch.annotation.Field.class);

                // 如果嵌套对象：
                /**
                 * {
                 *   "mappings": {
                 *     "properties": {
                 *       "region": {
                 *         "type": "keyword"
                 *       },
                 *       "manager": {
                 *         "properties": {
                 *           "age":  { "type": "integer" },
                 *           "name": {
                 *             "properties": {
                 *               "first": { "type": "text" },
                 *               "last":  { "type": "text" }
                 *             }
                 *           }
                 *         }
                 *       }
                 *     }
                 *   }
                 * }
                 */
                if (declaredAnnotation.type() == FieldType.OBJECT) {
                    // 获取当前类的对象-- Action
                    Class<?> type = f.getType();
                    Field[] df2 = type.getDeclaredFields();
                    builder.startObject(f.getName());
                    builder.startObject("properties");
                    // 遍历该对象中的所有属性
                    for (Field f2 : df2) {
                        if (f2.isAnnotationPresent(com.dal.elasticsearch.annotation.Field.class)) {
                            // 获取注解
                            com.dal.elasticsearch.annotation.Field declaredAnnotation2 = f2.getDeclaredAnnotation(com.dal.elasticsearch.annotation.Field.class);
                            builder.startObject(f2.getName());
                            builder.field("type", declaredAnnotation2.type().getType());
                            // keyword不需要分词
                            if (declaredAnnotation2.type() == FieldType.TEXT) {
                                builder.field("analyzer", declaredAnnotation2.analyzer().getType());
                            }
                            builder.endObject();
                        }
                    }
                    builder.endObject();
                    builder.endObject();

                }else{
                    builder.startObject(f.getName());
                    builder.field("type", declaredAnnotation.type().getType());
                    // keyword不需要分词
                    if (declaredAnnotation.type() == FieldType.TEXT) {
                        builder.field("analyzer", declaredAnnotation.analyzer().getType());
                    }
                    builder.endObject();
                }
            }
        }
        // 对应property
        builder.endObject();
        builder.endObject();
        return builder;
    }
}
